package models.users

import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import slick.jdbc.JdbcProfile

import java.sql.Timestamp
import java.time.LocalDateTime
import javax.inject.{Inject, Singleton}
import scala.concurrent.{ExecutionContext, Future}

@Singleton
class KingdeeUsersRepository @Inject()(protected val dbConfigProvider: DatabaseConfigProvider,
                                       ugRepo: UserGroupRepository)(implicit executionContext: ExecutionContext)
  extends HasDatabaseConfigProvider[JdbcProfile] {

  import profile.api._

  private class KingdeeUserTable(tag: Tag) extends Table[KingdeeUser](tag, "SYS_KINGDEE_USERS") {
    def id = column[Long]("ID", O.PrimaryKey)

    def acct_id = column[String]("ACCT_ID".toUpperCase()) // = models.CharField(max_length=20)

    def base_user_id = column[Option[Int]]("BASE_USER_ID".toUpperCase()) // = models.BigIntegerField(null=True,blank=True)

    def name = column[String]("NAME".toUpperCase()) // = models.CharField(max_length=20)

    def mobile = column[String]("MOBILE".toUpperCase()) // = models.CharField(max_length=20)

    def forbid_status = column[String]("FORBIDSTATUS".toUpperCase()) // = models.CharField(max_length=1)

    def disable_time = column[Option[Timestamp]]("FDISABLETIME".toUpperCase()) // = models.DateTimeField(null=True,blank=True)

    def fAppGroup = column[String]("FAPPGROUP".toUpperCase()) // = models.CharField(max_length=10)

    def status = column[Int]("STATUS".toUpperCase()) // = models.SmallIntegerField(default=0)

    def * = (
      id, acct_id, base_user_id, name, mobile, forbid_status, disable_time, fAppGroup, status
      ).<>((KingdeeUser.apply _).tupled, KingdeeUser.unapply)
  }

  private val kingdeeUserTable = TableQuery[KingdeeUserTable]

  private class KingdeeDataCenterTable(tag: Tag) extends Table[KingdeeDataCenter](tag, "SYS_KINGDEE_DATACENTER") {
    def id = column[String]("ID", O.PrimaryKey) // = models.CharField(primary_key=True,max_length=20)

    def name = column[String]("NAME") // = models.CharField(max_length=100)

    def test = column[Boolean]("TEST") // = models.BooleanField()

    def * = (id, name, test)
      .<>((KingdeeDataCenter.apply _).tupled, KingdeeDataCenter.unapply)
  }

  private val kingdeeDataCenterTabale = TableQuery[KingdeeDataCenterTable]

  private val accountTable = ugRepo.accountTable
  private val userInfoTable = ugRepo.userInfoTable

  /////////////////////////

  def kduserList() = db.run(kingdeeUserTable.map(f => f).result)

  def kddcList(page: Int = 1, limit: Int = 10) = {
    db.run(
      kingdeeDataCenterTabale
        .sortBy(_.id).drop((page - 1) * limit)
        .take(limit)
        .map(f => f)
        .result
    )
      .zip(db.run(kingdeeUserTable.length.result))
  }

  def kddcAll() = db.run(kingdeeDataCenterTabale.map(f=>(f.id,f.name)).result)

  def kddcCreate() = {}

  def kddcUpdate() = {}

  def accountAll() = db.run(accountTable.filter(_.is_active===1).sortBy(_.id).map(f=>(f.id,f.username)).result)

  def userFindby(name: String, mobile: String, status: Int, page: Int = 1, limit: Int = 10) = {
    val q = kingdeeUserTable
      .filterIf(name.nonEmpty)(_.name like s"%$name%")
      .filterIf(mobile.nonEmpty)(_.mobile === mobile)
      .filterIf(status != -1)(_.status === status)
    val res = q.sortBy(_.id).drop((page - 1) * limit).take(limit)
    val qr = for{
      (r,a) <- res joinLeft (accountTable) on (_.base_user_id === _.id)
      (r,d) <- res joinLeft( kingdeeDataCenterTabale) on (_.acct_id === _.id)
    } yield (r,a.map(_.username),d.map(_.name))
    val total = q.length.result
    db.run(qr.map(f => (f._1, f._2,f._3)).result).zip(db.run(total))
  }

  def findById(id: Long) = {
    val find = for {
      (gy, acc) <- kingdeeUserTable joinLeft accountTable on (_.base_user_id === _.id)
    } yield (gy.id, gy.name, gy.mobile, gy.status, acc.map(_.is_active))
    db.run(find.filter(_._1 === id).result)
  }

  def create(user: KingdeeUser) = db.run{
    accountTable.filter(_.mobile===user.mobile).map(f=>f.id).result
  }.flatMap { acc=>
    if (acc.isEmpty) db.run(kingdeeUserTable += user.copy(status = 9))
    else db.run(kingdeeUserTable += user.copy(base_user_id = acc.head))
  }

  def updateStatus(id: Long, status: Int) = db.run(
    if (status==0) kingdeeUserTable.filter(_.id === id).map(f => (f.status, f.disable_time)).update((0, Some(Timestamp.valueOf(LocalDateTime.now()))))
    else kingdeeUserTable.filter(_.id === id).map(f => f.status).update(status)
  )

  def updateBaseUsersId(id: Long, buid: Option[Int]) = db.run(kingdeeUserTable.filter(_.id === id).map(f => f.base_user_id).update(buid))

  def updateDisable(id: Long) = db.run {
    kingdeeUserTable.filter(_.id === id).map(f => f.status).result
  }.flatMap { r =>
    if (r.nonEmpty && r.head > 0)
      db.run(kingdeeUserTable.filter(_.id === id).map(f => (f.status, f.disable_time)).update((0, Some(Timestamp.valueOf(LocalDateTime.now()))))).zip(Future(0))
    else
      db.run(kingdeeUserTable.filter(_.id === id).map(f => f.status).update(2)).zip(Future(2))
  }

}
